package com.gitee.huxing.course.netty.gateway.factory.response;

import com.gitee.huxing.course.netty.gateway.factory.BusinessFactory;
import com.gitee.huxing.course.netty.gateway.filter.HttpBodyResponseFilter;
import com.gitee.huxing.course.netty.gateway.filter.HttpHeaderResponseFilter;
import com.gitee.huxing.course.netty.gateway.filter.HttpRequestFilter;
import com.gitee.huxing.course.netty.gateway.filter.HttpResponseFilter;
import com.gitee.huxing.course.netty.gateway.router.NettyRouter;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

/**
 * @Description:
 * @ProjectName: JavaCourse
 * @Package: com.gitee.huxing.course.netty.gateway.factory
 * @ClassName: ResponseFactory
 * @Author: huxing
 * @DateTime: 2021-08-21 下午3:53
 */
@Slf4j
@Component
@ConditionalOnBean(name = "responseFactory")
public class ResponseFactory extends BusinessFactory<FullHttpResponse, ChannelHandlerContext, HttpResponseFilter> {

    @PostConstruct
    public void init(){
        List<HttpResponseFilter> filters = new ArrayList<>();
        filters.add(new HttpHeaderResponseFilter());
        filters.add(new HttpBodyResponseFilter());
        setFilters(filters);
    }

    @Override
    public void processBussiness(FullHttpResponse response, ChannelHandlerContext channel) {
        // 返回的时候需要先处理过滤消息
        String message = response.content().toString(StandardCharsets.UTF_8);
        log.info("网关转发应答消息: {}", response.content().toString(StandardCharsets.UTF_8));
        FullHttpResponse body = new DefaultFullHttpResponse(HTTP_1_1, OK,
                Unpooled.wrappedBuffer(message.getBytes(StandardCharsets.UTF_8)));
        body.headers().set("requestTime", response.headers()
                .get("requestTime").toString());
        body.headers().set("Content-Type", "application/json");
        body.headers().setInt("Content-Length",
                body.content().readableBytes());
        // 调用处理流程
        this.process(body, channel);
    }

    @Override
    public FullHttpResponse processFilter(FullHttpResponse response, List<HttpResponseFilter> filters) {
        log.info("返回过滤处理");
        FullHttpResponse httpResponse = response.copy();
        for (HttpResponseFilter filter : filters){
            httpResponse = filter.filter(httpResponse);
        }
        log.info(httpResponse.content().toString(StandardCharsets.UTF_8));
        return httpResponse;
    }

    @Override
    public void processRouter(FullHttpResponse response) {
    }

    @Override
    public void send(FullHttpResponse response, ChannelHandlerContext channel) {
        // 消息处理
        ChannelHandlerContext context = getChannel();
        if (context != null) {
            // 请求时间
            String requestTime = response.headers().get("requestTime");
            // 响应时间
            String reponseTime = response.headers().get("responseTime");
            // 发送时间
            context.writeAndFlush(response);
            log.info("本次服务总共耗时: {}ms", timeOn(requestTime, reponseTime));
        } else {
            log.info("客户端收到响应消息: {}", response.content().toString(StandardCharsets.UTF_8));
        }
    }

    @Override
    public void err(FullHttpResponse object, ChannelHandlerContext channel, String err) {
    }

    /**
     * @Description:  计算服务耗时
     * @Author: huxing
     * @param requestTime
     * @param responseTime
     * @return long
     * @Date: 2021/8/21 下午9:58
     **/
    private long timeOn(String requestTime, String responseTime){
        // 起始时间
        LocalDateTime startTime = LocalDateTime.parse(requestTime);
        // 截止时间
        LocalDateTime endTime = LocalDateTime.parse(responseTime);
        // 时间差
        Duration duration = java.time.Duration.between(startTime, endTime);
        // 返回耗时
        return duration.toMillis();
    }
}
